<script setup lang="ts">

import {useRoute} from "vue-router";
import {
  DataTableColumns,
  FormInst,
  FormItemRule,
  FormRules,
  NBadge,
  NButton,
  NButtonGroup,
  NPopconfirm,
  NSpace,
  NTag,
  PaginationInfo,
  PaginationProps
} from "naive-ui";
import {SysDict} from "@/api/dict/types.ts";
import {dictApi} from "@/api/dict";
import {isEmpty, renderPermission, resetToNull} from "@/utils";
import {useDictStore} from "@/stores";

interface PageQuery {
  keyword?: string
  dictStatus?: number
  parentId?: string
}

enum ModeTypeEnum {
  ADD = '新增',
  MODIFY = '修改'
}

const dictStore = useDictStore();
const currentRoute = useRoute();
const parentDict = reactive<SysDict>(<SysDict>{})
const pageQuery = reactive<PageQuery>({
  keyword: undefined,
  dictStatus: undefined,
  parentId: undefined
})
const dictItemDisable = ref(true)
const tableLoading = ref(false);
const tableColumns = ref<DataTableColumns<SysDict>>([
  {title: '字典名称', key: 'dictName', render: row => tableDictNameRender(row)},
  {
    key: 'dictValue', align: 'center', title: (row: SysDict) => {
      let r = [h('span', {}, {default: () => '字典值'})]
      if (parentDict.dictValueType !== undefined) {
        r.push(dictStore.renderTag('dict-value-type', parentDict.dictValueType, 'small'));
      }
      return h(NSpace, {size: 'small', justify: 'center'}, {default: () => r})
    }
  },
  {title: '字典权重', key: 'dictWeight'},
  {title: '字典状态', key: 'dictStatus', render: row => dictStore.renderTag('common-status', row.dictStatus)},
  {title: '创建时间', key: 'createTime'},
  {title: '操作', key: 'action', align: 'center', render: row => tableActionRender(row)}
])
const tableData = ref<SysDict[]>([])
const tablePagination = reactive<PaginationProps>({
  simple: true,
  prefix: (info: PaginationInfo) => {
    return `共 ${info.itemCount} 条记录`
  },
  itemCount: 0,
  pageCount: 0
})

const drawerDetailShow = ref(false)
const drawerDetailTitle = ref<ModeTypeEnum | null>(null)
const drawerDetailFormRef = ref<FormInst | null>(null)
const drawerDetailFormRules = reactive<FormRules>({
  dictName: {required: true, message: '字典名称不能为空', trigger: 'blur'},
  dictValue: {
    required: true, trigger: 'blur', validator: (rule: FormItemRule, value: string) => {
      return new Promise<void>((resolve, reject) => {
        if (isEmpty(value)) {
          reject(new Error('字典值不能为空'))
        } else {
          drawerDetailFormModel.dictValueType === 0 && !/^[0-9]+$/.test(value) && reject(new Error('字典值必须为数字'));
          drawerDetailFormModel.dictValueType === 1 && !/^[0-9a-zA-Z-_]+$/.test(value) && reject(new Error('字典值必须为字母或数字'));
          resolve()
        }
      })
    }
  },
  dictStatus: {required: true, message: '字典状态不能为空', trigger: 'blur', type: 'number'}
})
const drawerDetailFormModel = reactive<SysDict>(<SysDict>{})
const drawerDetailSubmitLoading = ref(false)

onMounted(() => {
  initDictItem()
  dictStore.loadDict(['dict-value-type', 'dict-render-type', 'common-status'])
})

watch(() => currentRoute.query, () => {
  initDictItem()
})

const tableDictNameRender = (row: SysDict) => {
  const node = h(NTag, {type: row.dictRenderType}, {default: () => row.dictName});
  if (row.defaultItem === true) {
    return h(NBadge, {dot: true, type: 'success'}, {default: () => node})
  }
  return node
}

const tableActionRender = (row: SysDict) => {
  return h(NButtonGroup, {size: 'small'}, {
    default: () => [
      renderPermission(h(NButton, {
        type: 'primary',
        tertiary: true,
        onClick: () => handleClickModify(row)
      }, {default: () => '编辑'}), 'dict:item:modify'),
      h(NPopconfirm, {onPositiveClick: () => handleClickDelete(row)}, {
        trigger: () => renderPermission(h(NButton, {
          tertiary: true,
          type: 'error',
        }, {default: () => '删除'}), 'dict:delete'),
        default: () => `确定删除该(${row.dictName}/${row.dictCode})字典吗？`
      })
    ]
  })
}

const initDictItem = () => {
  if (currentRoute.query.parentId && currentRoute.query.parentId !== pageQuery.parentId) {
    pageQuery.parentId = currentRoute.query.parentId as string
    dictApi.detail(pageQuery.parentId).then(res => {
      Object.assign(parentDict, res.data)
    })
    dictItemDisable.value = false
    handlePageQuery()
  } else {
    dictItemDisable.value = true
    tableData.value = []
    tablePagination.itemCount = 0
    tablePagination.pageCount = 0
    tablePagination.page = 1
  }
}

const handlePageQuery = () => {
  tableLoading.value = true;
  dictApi.page({
    ...pageQuery,
    current: tablePagination.page ?? 1,
    size: tablePagination.pageSize ?? 20
  }).then(res => {
    tableData.value = res.data.records
    tablePagination.itemCount = res.data.total
    tablePagination.pageCount = res.data.pages
  }).finally(() => tableLoading.value = false)
}

const handleClickDelete = (row: SysDict) => {
  if (row.id != null) {
    dictApi.delete(row.id).then(res => {
      window.$message?.success(res.message)
      handlePageQuery()
    })
  }
}

const initDrawerDetail = (modelType: ModeTypeEnum) => {
  drawerDetailShow.value = true
  drawerDetailTitle.value = modelType
}

const handleClickAdd = () => {
  initDrawerDetail(ModeTypeEnum.ADD)
  drawerDetailFormModel.dictStatus = dictStore.getDictDefault('common-status').dictValue as number
  drawerDetailFormModel.dictRenderType = dictStore.getDictDefault('dict-render-type').dictValue as string
}

const handleClickModify = (row: SysDict) => {
  if (row.id != null) {
    dictApi.detail(row.id).then(res => {
      Object.assign(drawerDetailFormModel, res.data)
      initDrawerDetail(ModeTypeEnum.MODIFY)
    })
  }
}

const handleDrawerClose = () => {
  drawerDetailFormRef.value?.restoreValidation()
  resetToNull(drawerDetailFormModel)
  handlePageQuery()
}

const handleClickSubmit = () => {
  drawerDetailSubmitLoading.value = true
  drawerDetailFormRef.value?.validate((errors) => {
    if (!errors) {
      let data = drawerDetailFormModel;
      data.parentId = parentDict.id
      data.dictCode = parentDict.dictCode
      switch (drawerDetailTitle.value) {
        case ModeTypeEnum.ADD:
          dictApi.addItem(data).then(res => {
            window.$message?.success(res.message)
            drawerDetailShow.value = false
          })
          break
        case ModeTypeEnum.MODIFY:
          dictApi.modifyItem(data).then(res => {
            window.$message?.success(res.message)
            drawerDetailShow.value = false
          })
      }
    }
  }).finally(() => drawerDetailSubmitLoading.value = false)
}

</script>

<template>
  <n-card class="dict-item" flex-1 h-fit>
    <template #header>
      <n-space>
        <n-button
            :disabled="dictItemDisable"
            secondary
            @click="handlePageQuery"
            :loading="tableLoading"
            v-p="'dict:page'"
        >查询
        </n-button>
        <n-button
            :disabled="dictItemDisable"
            secondary
            type="primary"
            @click="handleClickAdd"
            v-p="'dict:item:add'"
        >新增
        </n-button>
      </n-space>
    </template>
    <n-data-table
        remote
        :loading="tableLoading"
        :disabled="dictItemDisable"
        :columns="tableColumns"
        :data="tableData"
        :pagination="tablePagination"
    />
  </n-card>
  <n-drawer
      v-model:show="drawerDetailShow"
      :on-after-leave="handleDrawerClose"
      :width="502"
      :auto-focus="false"
      :mask-closable="false"
  >
    <n-drawer-content
        :title="drawerDetailTitle"
        closable
    >
      <n-form
          ref="drawerDetailFormRef"
          :rules="drawerDetailFormRules"
          :model="drawerDetailFormModel"
      >
        <n-grid :cols="24" :x-gap="12">
          <n-form-item-gi v-if="drawerDetailFormModel.id" :span="24" label="主键">
            <n-tag type="primary">{{ drawerDetailFormModel.id }}</n-tag>
          </n-form-item-gi>
          <n-form-item-gi :span="12" label="字典名称" path="dictName">
            <n-input v-model:value="drawerDetailFormModel.dictName" placeholder="请输入字典名称"/>
          </n-form-item-gi>
          <n-form-item-gi :span="12" label="父级字典">
            <n-tag type="success">{{ parentDict.dictName }}</n-tag>
          </n-form-item-gi>
          <n-form-item-gi :span="24" label="字典值" path="dictValue">
            <n-input-group>
              <dict-tag dict-code="dict-value-type" :dict-value="parentDict.dictValueType" size="large"/>
              <n-input
                  v-model:value="drawerDetailFormModel.dictValue"
                  placeholder="请输入字典值"
              />
            </n-input-group>
          </n-form-item-gi>
          <n-form-item-gi :span="12" label="字典渲染类型">
            <n-select
                v-model:value="drawerDetailFormModel.dictRenderType"
                :options="dictStore.getDictTagOptions('dict-render-type')"
                placeholder="请选择字典渲染类型"
            />
          </n-form-item-gi>
          <n-form-item-gi :span="12" label="字典状态" path="dictStatus">
            <n-select
                v-model:value="drawerDetailFormModel.dictStatus"
                :options="dictStore.getDictTagOptions('common-status')"
                placeholder="请选择字典状态"
            />
          </n-form-item-gi>
          <n-form-item-gi :span="12" label="字典权重">
            <n-input-number :default-value="0" v-model:value="drawerDetailFormModel.dictWeight"
                            placeholder="请输入字典权重"/>
          </n-form-item-gi>
          <n-form-item-gi :span="12" label="默认项">
            <n-switch v-model:value="drawerDetailFormModel.defaultItem"/>
          </n-form-item-gi>
          <n-form-item-gi :span="24" label="字典备注">
            <n-input type="textarea" v-model:value="drawerDetailFormModel.dictDesc" placeholder="请输入字典备注"/>
          </n-form-item-gi>
        </n-grid>
      </n-form>
      <template #footer>
        <n-button type="primary" @click="handleClickSubmit" :loading="drawerDetailSubmitLoading">提交</n-button>
      </template>
    </n-drawer-content>
  </n-drawer>
</template>

<style scoped>

</style>
